package edu.ccut.saturn.studio.export.model;

import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.eclipse.draw2d.geometry.Point;
import org.eclipse.swt.widgets.Shell;
import org.w3c.dom.Document;
import org.w3c.dom.Node;

import edu.ccut.saturn.studio.core.exception.XMLException;
import edu.ccut.saturn.studio.core.util.eclipse.Messages;
import edu.ccut.saturn.studio.core.util.freemaker.FreemarkerUtils;
import edu.ccut.saturn.studio.core.util.xml.SaturnW3CUtil;
import edu.ccut.saturn.studio.export.createhtml.Parameters;
import edu.ccut.saturn.studio.wfg.dialog.endactivitydialog.SaturnEndActivityDialog;
import edu.ccut.saturn.studio.wfg.model.Shape;
import edu.ccut.saturn.studio.wfg.utils.ModelXmlUtils;
import edu.ccut.saturn.studio.wfg.wfgmodel.LogicKeyAttribute;
import edu.ccut.saturn.studio.wfg.wfgmodel.SaturnEndNode;
import edu.ccut.saturn.studio.wfg.wfgmodel.SaturnInformationNode;
import edu.ccut.saturn.studio.wfg.xml.loader.NodeLoader;
import edu.ccut.saturn.studio.wfg.xml.loader.SaturnAutoActivityNodeLoader;
import edu.ccut.saturn.studio.wfg.xml.loader.SaturnEndNodeLoader;
import edu.ccut.saturn.studio.wfg.xml.loader.SaturnHumanNodeLoader;
import edu.ccut.saturn.studio.wfg.xml.loader.SaturnInfoNodeLoader;
import edu.ccut.saturn.studio.wfg.xml.loader.SaturnRouterLoader;
import edu.ccut.saturn.studio.wfg.xml.loader.SaturnStartNodeLoader;
import edu.ccut.saturn.studio.wfg.xml.loader.SaturnSubActivityNodeLoader;

/**
 * 生成工作流构件的具体实现类
 * 
 * @author 杨艳斌
 * @author 施洪洁
 * @version 1.1 2009.12.11
 */
public class Wfg {

	protected static final String SEPARATOR = File.separator;
	private static String filename;
	private static SaturnInformationNode infonode;
	private static SaturnEndNode endnode;
	private static String info;
	
	/**
	 * 创建工作流构件的html文档
	 * 
	 * @param file,filePath
	 * @return String
	 * @throws XMLException
	 */
	public static String createComponentHtml(File file, String filePath) throws XMLException {

		Document doc = SaturnW3CUtil.getDocument(file.getAbsolutePath());
		filename = file.getName().replace(".", "-");
		
		Node root = doc.getDocumentElement();
		List<Node> ConnectionNodes = SaturnW3CUtil.getChildrenByName(
				root, "connection");
		
		List<Shape> shapes = ModelXmlUtils.loadModels(doc, new NodeLoader[] {
				new SaturnInfoNodeLoader(), new SaturnStartNodeLoader(),
				new SaturnEndNodeLoader(), new SaturnHumanNodeLoader(),
				new SaturnRouterLoader(), new SaturnAutoActivityNodeLoader(),
				new SaturnSubActivityNodeLoader() });
		generateInfo(shapes, filePath, ConnectionNodes);

		return info;
	}
	
	/**
	 * 创建工作流构件的html文档的具体实现方法
	 * 
	 * @param shapes,filePath,connectionNodes
	 * @return 
	 */
	private static void generateInfo(List<Shape> shapes, String filePath, List<Node> connectionNodes) {

		Map<String, List<?>> summm = new HashMap<String, List<?>>();
		String indextempalatePath = "template/export/wfg/index";
		List<Parameters> values = new ArrayList<Parameters>();
		List<Parameters> basicvaluse = new ArrayList<Parameters>();
		List<Parameters> imageinfos = new ArrayList<Parameters>();
		List<Parameters> addheight = new ArrayList<Parameters>();
		List<Parameters> resizes = new ArrayList<Parameters>();
		Map<String, Point> locations = new HashMap<String, Point>();
		Parameters param = new Parameters();
		Parameters temppara = new Parameters();
		int minheight = 10000;
		int minwidth = 10000;
		int maxwidth = 0;
		int maxheight = 0;
		double tempheight = 0.0;
		double tempwidth = 0.0;
		double resize = 1.0;
		boolean flag = false;															//是否对图片进行缩放
		
		//遍历编辑器中的节点，并获取所需的信息
		for (int j = 0; j < shapes.size(); j++) {
			Parameters para = new Parameters();
			String imagename = "";														//节点图片的名称
			
			if (shapes.get(j) instanceof SaturnInformationNode) {
				infonode = (SaturnInformationNode) shapes.get(j);
				basicvaluse.add(createInformationHtml(infonode, filePath));
				continue;
			} else if (shapes.get(j) instanceof SaturnEndNode) {
				endnode = (SaturnEndNode) shapes.get(j);
				values.add(createEndHtml(endnode, filePath));
				imagename = "end";
			} else {
				 Parameters paranode = shapes.get(j).createNodeHtml(filePath);
				 values.add(paranode);
				 imagename = paranode.getImagename();
			}
			 
			//获得编辑器中图元的边界值
			 if (shapes.get(j).getLocation().y > maxheight) {
					maxheight = shapes.get(j).getLocation().y;
			 } 
			 if (shapes.get(j).getLocation().y < minheight) {
			 	  	minheight = shapes.get(j).getLocation().y;
			 }
			 if (shapes.get(j).getLocation().x > maxwidth) {
				 	maxwidth = shapes.get(j).getLocation().x;
			 } 
			 if (shapes.get(j).getLocation().x < minwidth) {
				 	minwidth = shapes.get(j).getLocation().x;
			 }
			 
			//获得图片的相关信息
			para.setWidth(shapes.get(j).getLocation().x);
			para.setHeight(shapes.get(j).getLocation().y);
			para.setResize(12*resize);													//调整箭头的缩放比
			para.setNodeName(shapes.get(j).getName());
			para.setInfourl( shapes.get(j).getName() + ".html");
			para.setImagePath("../../../../tools/images/nodes/workflow/" + imagename + ".gif");
			
			locations.put(shapes.get(j).getId(), shapes.get(j).getLocation());
		    imageinfos.add(para); 
		    
		    if (shapes.get(j).getLocation().x > 660) {
		    	flag = true;
		    }
		}
		
		//图片大小进行适当调整
		if (minheight < 0) {
			tempheight = 0 - minheight;
			flag = true;
			for (Parameters parameter : imageinfos) {
				parameter.setHeight(tempheight + parameter.getHeight() + 15);
			}
		}
		if (minwidth < 0) {
			tempwidth = 0 - minwidth;
			flag = true;
			for (Parameters parameter : imageinfos) {
				parameter.setWidth((double)tempwidth + parameter.getWidth() + 15);
			}
		}
			
		if (flag == true) {
			resize = 550/(double)(maxwidth - minwidth);									//获得图片缩放比	
			imageinfos = relocation(imageinfos,resize);									//缩放图片对象
		}	
		
		
		param.setMaxheight(resize*(tempheight + maxheight + 100));					//设定流程图表格的最大高度
		addheight.add(param);
		temppara.setResize(resize);
		resizes.add(temppara);
		
		summm.put("resizes", resizes);
		summm.put("basicvaluse", basicvaluse);
		summm.put("maxheight",addheight);
		summm.put("imageinfos", imageinfos);
		summm.put("linklines", createLinkLines(locations,
							connectionNodes, tempheight, tempwidth, resize));        //创建流程图中的连线
		summm.put("valuse", values);

		FreemarkerUtils.writeTemplateToFile(indextempalatePath, summm, filePath
				+ File.separator + filename + ".html");

	}
	
	/**
	 * 重新调整图片对象的大小
	 * 
	 * @param imageinfos,resize
	 * @return List<Parameters>
	 */
	private static List<Parameters> relocation(List<Parameters> imageinfos, double resize) {
		
		for (Parameters parameter : imageinfos) {
		    parameter.setWidth((parameter.getWidth())*resize);
			parameter.setHeight((parameter.getHeight())*resize);
			parameter.setResize((parameter.getResize())*resize);
		}

		return imageinfos;
	}
	
	/**
	 * 创建工作流构件流程图中的连线
	 * 
	 * @param locations,connectionNodes, tempheight, tempwidth resize
	 * @return List<Parameters>
	 */
	private static List<Parameters> createLinkLines(Map<String, Point> locations,
		List<Node> connectionNodes, double tempheight, double tempwidth, double resize) {
	
		List<Parameters> linklines = new ArrayList<Parameters>();
	
		for (Node ConnectionNode : connectionNodes) {
			Parameters para = new Parameters();
			
			if (locations.get(SaturnW3CUtil.
					getNodeAttributeValue(ConnectionNode, "source")) != null && 
					locations.get(SaturnW3CUtil.
							getNodeAttributeValue(ConnectionNode, "target")) != null) {
				
				para.setSourcewidth(resize*((double)(locations.get(SaturnW3CUtil.
						getNodeAttributeValue(ConnectionNode, "source")).x  + 25) + tempwidth));
				para.setSourceheight(resize*((double)(locations.get(SaturnW3CUtil.
						getNodeAttributeValue(ConnectionNode, "source")).y  + 25) + tempheight));
				para.setTargetwidth(resize*((double)(locations.get(SaturnW3CUtil.
						getNodeAttributeValue(ConnectionNode, "target")).x  + 25) + tempwidth));
				para.setTargetheight(resize*((double)(locations.get(SaturnW3CUtil. 	
						getNodeAttributeValue(ConnectionNode, "target")).y  + 25) + tempheight));
				
				para.setWidthresize(5*resize);
				para.setHeightresize(11*resize);
				
				linklines.add(para);
			}
		}
		
		return linklines;
	}
	
	/**
	 * 创建结束节点的html文档
	 * 
	 * @param endnode,filePath
	 * @return Parameters
	 */
	private static Parameters createEndHtml(SaturnEndNode endnode, String filePath) {
		
		List<Parameters> basicvaluse = new ArrayList<Parameters>();
		Shell parentshell = null;
		SaturnEndActivityDialog dialog = new SaturnEndActivityDialog(parentshell,
				endnode);
		List<LogicKeyAttribute> parameters = (List<LogicKeyAttribute>) dialog
				.getKeys();
		Map<String, List<?>> summm = new HashMap<String, List<?>>();
		String name = endnode.getName();
		Parameters para = new Parameters();

		para.setName(endnode.getName());
		para.setId(endnode.getId());
		para.setPolyMode(transfer(endnode.getPolymeMode()));
		para.setDescription(endnode.getDescription());
		basicvaluse.add(para);

		para.setInfourl(name + ".html");
		para.setInfoname(name);
		para.setDescription(endnode.getDescription());
		para.setNodeType(Messages.getString("Wfg.EndNode")); //$NON-NLS-1$
		summm.put("parameters", parameters);
		summm.put("basicvaluse", basicvaluse);
		String templatePath = "template/export/wfg/end";
		String Path = filePath + File.separator + name + ".html";
		FreemarkerUtils.writeTemplateToFile(templatePath, summm, Path);

		return para;
	}
	
	
	/**
	 * 对聚合模式进行转换
	 * 
	 * @param startPolicy
	 * @return Parameters
	 */
	private static String transfer(String polymeMode) {
		if (polymeMode.equals("1")) {
			return Messages.getString("Wfg.OnePoly"); //$NON-NLS-1$
		} else if (polymeMode.endsWith("2")) {
			return Messages.getString("Wfg.AllPoly"); //$NON-NLS-1$
		} else {
			return Messages.getString("Wfg.ManyPoly"); //$NON-NLS-1$
		}
	}
	
	/**
	 * 创建工作流构件基本信息的html文档
	 * 
	 * @param humannode,filePath
	 * @return Parameters
	 */
	private static Parameters createInformationHtml(
			SaturnInformationNode infonode, String filePath) {
		Parameters para = new Parameters();

		para.setKey(infonode.getKey());
		para.setVersion(infonode.getVersion());
		para.setAuthor(infonode.getAuthor());
		para.setName(infonode.getName());
		para.setDescription(infonode.getDescription());

		info = infonode.getDescription();
		return para;
	}
}
